package cn.com.anysdk.core.util;

import org.apache.commons.io.FilenameUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文件操作工具类
 */
public class FileUtils {
    private FileUtils() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 判断文件是否存在
     *
     * @param file 文件
     * @return 是否存在
     */
    public static boolean exists(File file) {
        return file != null && file.exists();
    }

    /**
     * 判断文件是否存在
     *
     * @param path 文件路径
     * @return 是否存在
     */
    public static boolean exists(String path) {
        return path != null && new File(path).exists();
    }

    /**
     * 判断文件是否为目录
     *
     * @param file 文件
     * @return 是否为目录
     */
    public static boolean isDirectory(File file) {
        return file != null && file.isDirectory();
    }

    /**
     * 判断文件是否为文件
     *
     * @param file 文件
     * @return 是否为文件
     */
    public static boolean isFile(File file) {
        return file != null && file.isFile();
    }

    /**
     * 获取文件大小
     *
     * @param file 文件
     * @return 文件大小（字节）
     */
    public static long size(File file) {
        return file != null ? file.length() : 0;
    }

    /**
     * 获取文件扩展名
     *
     * @param file 文件
     * @return 扩展名
     */
    public static String getExtension(File file) {
        return file != null ? FilenameUtils.getExtension(file.getName()) : null;
    }

    /**
     * 获取文件名（不含扩展名）
     *
     * @param file 文件
     * @return 文件名
     */
    public static String getBaseName(File file) {
        return file != null ? FilenameUtils.getBaseName(file.getName()) : null;
    }

    /**
     * 获取文件名（含扩展名）
     *
     * @param file 文件
     * @return 文件名
     */
    public static String getName(File file) {
        return file != null ? file.getName() : null;
    }

    /**
     * 获取文件路径
     *
     * @param file 文件
     * @return 文件路径
     */
    public static String getPath(File file) {
        return file != null ? file.getPath() : null;
    }

    /**
     * 获取文件绝对路径
     *
     * @param file 文件
     * @return 绝对路径
     */
    public static String getAbsolutePath(File file) {
        return file != null ? file.getAbsolutePath() : null;
    }

    /**
     * 获取文件规范路径
     *
     * @param file 文件
     * @return 规范路径
     */
    public static String getCanonicalPath(File file) {
        try {
            return file != null ? file.getCanonicalPath() : null;
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 创建目录
     *
     * @param dir 目录
     * @return 是否成功
     */
    public static boolean mkdir(File dir) {
        return dir != null && dir.mkdir();
    }

    /**
     * 创建目录（包括父目录）
     *
     * @param dir 目录
     * @return 是否成功
     */
    public static boolean mkdirs(File dir) {
        return dir != null && dir.mkdirs();
    }

    /**
     * 创建文件
     *
     * @param file 文件
     * @return 是否成功
     */
    public static boolean createFile(File file) {
        try {
            return file != null && file.createNewFile();
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 删除文件
     *
     * @param file 文件
     * @return 是否成功
     */
    public static boolean delete(File file) {
        return file != null && file.delete();
    }

    /**
     * 删除文件或目录
     *
     * @param file 文件或目录
     * @return 是否成功
     */
    public static boolean deleteQuietly(File file) {
        return org.apache.commons.io.FileUtils.deleteQuietly(file);
    }

    /**
     * 删除目录及其内容
     *
     * @param dir 目录
     * @return 是否成功
     */
    public static boolean deleteDirectory(File dir) {
        try {
            org.apache.commons.io.FileUtils.deleteDirectory(dir);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 复制文件
     *
     * @param src 源文件
     * @param dest 目标文件
     * @return 是否成功
     */
    public static boolean copy(File src, File dest) {
        try {
            org.apache.commons.io.FileUtils.copyFile(src, dest);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 复制目录
     *
     * @param src 源目录
     * @param dest 目标目录
     * @return 是否成功
     */
    public static boolean copyDirectory(File src, File dest) {
        try {
            org.apache.commons.io.FileUtils.copyDirectory(src, dest);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 移动文件
     *
     * @param src 源文件
     * @param dest 目标文件
     * @return 是否成功
     */
    public static boolean move(File src, File dest) {
        try {
            org.apache.commons.io.FileUtils.moveFile(src, dest);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 移动目录
     *
     * @param src 源目录
     * @param dest 目标目录
     * @return 是否成功
     */
    public static boolean moveDirectory(File src, File dest) {
        try {
            org.apache.commons.io.FileUtils.moveDirectory(src, dest);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 读取文件内容
     *
     * @param file 文件
     * @return 文件内容
     */
    public static String read(File file) {
        try {
            return org.apache.commons.io.FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 读取文件内容
     *
     * @param file 文件
     * @param charset 字符集
     * @return 文件内容
     */
    public static String read(File file, Charset charset) {
        try {
            return org.apache.commons.io.FileUtils.readFileToString(file, charset);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 写入文件内容
     *
     * @param file 文件
     * @param content 内容
     * @return 是否成功
     */
    public static boolean write(File file, String content) {
        try {
            org.apache.commons.io.FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 写入文件内容
     *
     * @param file 文件
     * @param content 内容
     * @param charset 字符集
     * @return 是否成功
     */
    public static boolean write(File file, String content, Charset charset) {
        try {
            org.apache.commons.io.FileUtils.writeStringToFile(file, content, charset);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 追加文件内容
     *
     * @param file 文件
     * @param content 内容
     * @return 是否成功
     */
    public static boolean append(File file, String content) {
        try {
            org.apache.commons.io.FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8, true);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 追加文件内容
     *
     * @param file 文件
     * @param content 内容
     * @param charset 字符集
     * @return 是否成功
     */
    public static boolean append(File file, String content, Charset charset) {
        try {
            org.apache.commons.io.FileUtils.writeStringToFile(file, content, charset, true);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 读取文件内容为字节数组
     *
     * @param file 文件
     * @return 字节数组
     */
    public static byte[] readBytes(File file) {
        try {
            return org.apache.commons.io.FileUtils.readFileToByteArray(file);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 写入字节数组到文件
     *
     * @param file 文件
     * @param data 字节数组
     * @return 是否成功
     */
    public static boolean writeBytes(File file, byte[] data) {
        try {
            org.apache.commons.io.FileUtils.writeByteArrayToFile(file, data);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 获取目录下的所有文件
     *
     * @param dir 目录
     * @return 文件列表
     */
    public static List<File> listFiles(File dir) {
        if (dir == null || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        File[] files = dir.listFiles();
        return files != null ? List.of(files) : new ArrayList<>();
    }

    /**
     * 获取目录下的所有文件（递归）
     *
     * @param dir 目录
     * @return 文件列表
     */
    public static List<File> listFilesRecursively(File dir) {
        if (dir == null || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        try {
            return Files.walk(dir.toPath())
                    .map(Path::toFile)
                    .filter(File::isFile)
                    .collect(Collectors.toList());
        } catch (IOException e) {
            return new ArrayList<>();
        }
    }

    /**
     * 获取目录下的所有目录
     *
     * @param dir 目录
     * @return 目录列表
     */
    public static List<File> listDirectories(File dir) {
        if (dir == null || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        File[] files = dir.listFiles();
        return files != null ? List.of(files).stream().filter(File::isDirectory).collect(Collectors.toList()) : new ArrayList<>();
    }

    /**
     * 获取目录下的所有目录（递归）
     *
     * @param dir 目录
     * @return 目录列表
     */
    public static List<File> listDirectoriesRecursively(File dir) {
        if (dir == null || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        try {
            return Files.walk(dir.toPath())
                    .map(Path::toFile)
                    .filter(File::isDirectory)
                    .collect(Collectors.toList());
        } catch (IOException e) {
            return new ArrayList<>();
        }
    }

    /**
     * 获取目录大小
     *
     * @param dir 目录
     * @return 目录大小（字节）
     */
    public static long getDirectorySize(File dir) {
        if (dir == null || !dir.isDirectory()) {
            return 0;
        }
        try {
            return Files.walk(dir.toPath())
                    .map(Path::toFile)
                    .filter(File::isFile)
                    .mapToLong(File::length)
                    .sum();
        } catch (IOException e) {
            return 0;
        }
    }

    /**
     * 获取文件最后修改时间
     *
     * @param file 文件
     * @return 最后修改时间
     */
    public static long getLastModified(File file) {
        return file != null ? file.lastModified() : 0;
    }

    /**
     * 设置文件最后修改时间
     *
     * @param file 文件
     * @param time 时间
     * @return 是否成功
     */
    public static boolean setLastModified(File file, long time) {
        return file != null && file.setLastModified(time);
    }

    /**
     * 获取文件权限
     *
     * @param file 文件
     * @return 权限
     */
    public static String getPermissions(File file) {
        if (file == null) {
            return null;
        }
        try {
            return Files.getPosixFilePermissions(file.toPath()).toString();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 设置文件权限
     *
     * @param file 文件
     * @param permissions 权限
     * @return 是否成功
     */
    public static boolean setPermissions(File file, String permissions) {
        if (file == null || permissions == null) {
            return false;
        }
        try {
            Files.setPosixFilePermissions(file.toPath(), java.nio.file.attribute.PosixFilePermissions.fromString(permissions));
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 获取文件所有者
     *
     * @param file 文件
     * @return 所有者
     */
    public static String getOwner(File file) {
        if (file == null) {
            return null;
        }
        try {
            return Files.getOwner(file.toPath()).getName();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 设置文件所有者
     *
     * @param file 文件
     * @param owner 所有者
     * @return 是否成功
     */
    public static boolean setOwner(File file, String owner) {
        if (file == null || owner == null) {
            return false;
        }
        try {
            java.nio.file.attribute.UserPrincipalLookupService lookupService = file.toPath().getFileSystem().getUserPrincipalLookupService();
            java.nio.file.attribute.UserPrincipal userPrincipal = lookupService.lookupPrincipalByName(owner);
            Files.setOwner(file.toPath(), userPrincipal);
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 获取文件组
     *
     * @param file 文件
     * @return 组
     */
    public static String getGroup(File file) {
        if (file == null) {
            return null;
        }
        try {
            return Files.getAttribute(file.toPath(), "group").toString();
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 设置文件组
     *
     * @param file 文件
     * @param group 组
     * @return 是否成功
     */
    public static boolean setGroup(File file, String group) {
        if (file == null || group == null) {
            return false;
        }
        try {
            Files.setAttribute(file.toPath(), "group", group);
            return true;
        } catch (IOException e) {
            return false;
        }
    }
}